package main

import (
	"time"
	"strings"
	"fmt"
	"net/url"
	"github.com/satori/go.uuid"
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"net/http"
	"io/ioutil"
)

const sortQueryString_fmt string =
	"AccessKeyId=%s"+
		"&Action=SendSms"+
		"&Format=JSON"+
		"&OutId=123"+
		"&PhoneNumbers=%s"+
		"&RegionId=cn-hangzhou"+
		"&SignName=%s"+
		"&SignatureMethod=HMAC-SHA1"+
		"&SignatureNonce=%s"+
		"&SignatureVersion=1.0"+
		"&TemplateCode=%s"+
		"&TemplateParam=%s"+
		"&Timestamp=%s"+
		"&Version=2017-05-25"

func encode_local(encode_str string) string{
	urlencode := url.QueryEscape(encode_str)
	urlencode = strings.Replace(urlencode,"+","%%20",-1)
	urlencode = strings.Replace(urlencode,"*","%2A",-1)
	urlencode = strings.Replace(urlencode,"%%7E","~",-1)
	urlencode = strings.Replace(urlencode,"/","%%2F",-1)
	return urlencode
}

func main() {
	const token string = "t4tOF3ejvwGOFlaPA8tCNb2HWCh21j&" // 阿里云 accessSecret 注意这个地方要添加一个 &

	AccessKeyId := "LTAIW7T4OtEAhw8X" // 自己的阿里云 accessKeyID
	PhoneNumbers := "18002357267"  // 发送目标的手机号
	SignName := url.QueryEscape("汇脉宝")
	SignatureNonce,_ := uuid.NewV4()
	TemplateCode := "SMS_117290028"
	TemplateParam := url.QueryEscape("{\"code\":\"123456\"}")
	Timestamp := url.QueryEscape(time.Now().UTC().Format("2006-01-02T15:04:05Z"))

	sortQueryString := fmt.Sprintf(sortQueryString_fmt,
		AccessKeyId,
		PhoneNumbers,
		SignName,
		SignatureNonce,
		TemplateCode,
		TemplateParam,
		Timestamp,
	)

	urlencode := encode_local(sortQueryString)
	sign_str := fmt.Sprintf("GET&%%2F&%s",urlencode)

	key := []byte(token)
	mac := hmac.New(sha1.New, key)
	mac.Write([]byte(sign_str))
	signture := base64.StdEncoding.EncodeToString(mac.Sum(nil))
	signture = encode_local(signture)
	//fmt.Println(signture)
	//fmt.Printf("http://dysmsapi.aliyuncs.com/?Signature=%s&%s\n",signture,sortQueryString)
	url := fmt.Sprintf("http://dysmsapi.aliyuncs.com/?Signature=%s&%s",signture,sortQueryString)

	httpGet(url)
}

func httpGet(url string) {
	resp, err := http.Get(url)
	if err != nil {
		// handle error
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		// handle error
	}

	fmt.Println(string(body))
}